<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>日志管理系统</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net.net/npm/font-awesome@4.7.0/css/css/font-awesome.min.css" rel="stylesheet">
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#165DFF',
                        secondary: '#6B7280',
                        success: '#10B981',
                        warning: '#F59E0B',
                        danger: '#EF4444',
                        dark: '#1F2937',
                        light: '#F3F4F6'
                    },
                    fontFamily: {
                        sans: ['Inter', 'system-ui', 'sans-serif'],
                    },
                }
            }
        }
    </script>
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .log-container {
                height: calc(100vh - 240px);
            }
            .log-line {
                white-space: pre-wrap;
                word-break: break-all;
            }
            .breadcrumb-item:not(:last-child)::after {
                content: "/";
                margin: 0 8px;
                color: #9CA3AF;
            }
        }
    </style>
</head>
<body class="bg-gray-50 font-sans">
    <div class="container mx-auto px-4 py-8 max-w-7xl">
        <header class="mb-8">
            <h1 class="text-[clamp(1.5rem,3vw,2.5rem)] font-bold text-dark mb-2">
                <i class="fa fa-file-text-o text-primary mr-2"></i>日志管理系统
            </h1>
            <p class="text-secondary">多层级日志文件夹浏览与管理</p>
        </header>

        <!-- 导航控制区 -->
        <div class="bg-white rounded-lg shadow-md p-4 mb-6">
            <div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4">
                <!-- 面包屑导航 -->
                <div class="flex flex-wrap items-center text-sm">
                    <span class="breadcrumb-item">
                        <button id="rootDirBtn" class="text-primary hover:underline flex items-center">
                            <i class="fa fa-folder-open mr-1"></i>日志根目录
                        </button>
                    </span>
                    <div id="breadcrumbContainer"></div>
                </div>
                
                <!-- 导航控制按钮 -->
                <div class="flex gap-2">
                    <button id="backBtn" class="bg-gray-200 hover:bg-gray-300 px-3 py-1 rounded flex items-center disabled:opacity-50 disabled:cursor-not-allowed" disabled>
                        <i class="fa fa-arrow-left mr-1"></i>上一级
                    </button>
                    <button id="forwardBtn" class="bg-gray-200 hover:bg-gray-300 px-3 py-1 rounded flex items-center disabled:opacity-50 disabled:cursor-not-allowed" disabled>
                        <i class="fa fa-arrow-right mr-1"></i>下一级
                    </button>
                    <button id="refreshDirBtn" class="bg-gray-200 hover:bg-gray-300 px-3 py-1 rounded flex items-center">
                        <i class="fa fa-refresh mr-1"></i>刷新
                    </button>
                </div>
            </div>
            
            <!-- 搜索框 -->
            <div class="mt-4 relative">
                <input 
                    type="text" 
                    id="itemFilter" 
                    placeholder="搜索文件夹或文件..." 
                    class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/50"
                >
                <i class="fa fa-search absolute right-3 top-3 text-gray-400"></i>
            </div>
        </div>

        <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
            <!-- 文件夹和文件列表 -->
            <div class="lg:col-span-1 bg-white rounded-lg shadow-md overflow-hidden">
                <div class="p-4 bg-primary text-white">
                    <h2 class="font-semibold text-lg flex items-center">
                        <i class="fa fa-folder-open mr-2"></i>
                        <span>目录内容</span>
                        <span id="itemCount" class="ml-2 text-sm bg-white/20 px-2 py-0.5 rounded-full">0 项</span>
                    </h2>
                </div>
                <div id="directoryContent" class="p-4 max-h-[calc(100vh-320px)] overflow-y-auto">
                    <!-- 目录内容将通过JavaScript动态加载 -->
                    <div class="flex justify-center p-8 text-gray-500">
                        <i class="fa fa-circle-o-notch fa-spin mr-2"></i>加载目录内容中...
                    </div>
                </div>
            </div>

            <!-- 日志内容显示 -->
            <div class="lg:col-span-2 bg-white rounded-lg shadow-md overflow-hidden">
                <div class="p-4 bg-gray-800 text-white flex justify-between items-center">
                    <h2 class="font-semibold text-lg">
                        <i class="fa fa-file-text mr-2"></i><span id="currentFileName">请选择日志文件</span>
                    </h2>
                    <div>
                        <button id="downloadBtn" class="bg-primary hover:bg-primary/90 text-white px-4 py-2 rounded-lg mr-2 disabled:opacity-50 disabled:cursor-not-allowed transition" disabled>
                            <i class="fa fa-download mr-1"></i>下载
                        </button>
                        <button id="refreshFileBtn" class="bg-gray-600 hover:bg-gray-500 text-white px-4 py-2 rounded-lg disabled:opacity-50 disabled:cursor-not-allowed transition" disabled>
                            <i class="fa fa-refresh mr-1"></i>刷新
                        </button>
                    </div>
                </div>
                <div id="logContentContainer" class="p-4 log-container overflow-y-auto bg-gray-900 text-gray-100 font-mono text-sm">
                    <div class="flex justify-center items-center h-full text-gray-400">
                        <div class="text-center">
                            <i class="fa fa-file-text-o text-5xl mb-4"></i>
                            <p>浏览左侧目录并选择日志文件查看内容</p>
                        </div>
                    </div>
                </div>
                <div class="p-4 bg-gray-100 text-sm text-secondary flex justify-between">
                    <div>
                        <span id="logStats">未选择文件</span>
                    </div>
                    <div>
                        <select id="logLevelFilter" class="bg-white border border-gray-300 rounded px-2 py-1 text-sm" disabled>
                            <option value="all">所有级别</option>
                            <option value="INFO">INFO</option>
                            <option value="WARN">WARN</option>
                            <option value="ERROR">ERROR</option>
                            <option value="FATAL">FATAL</option>
                        </select>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script>
        // API基础地址，根据实际情况修改
        const API_BASE_URL = 'https://localhost:7081/api/logs';
        
        // 导航状态管理
        let currentPath = '';          // 当前路径（相对于Logs根目录）
        let pathHistory = [];          // 路径历史记录
        let historyIndex = -1;         // 当前历史记录索引
        let currentFile = null;        // 当前选中的日志文件
        
        // 页面加载完成后初始化
        document.addEventListener('DOMContentLoaded', () => {
            // 加载根目录内容
            loadDirectoryContent('');
            
            // 绑定事件
            document.getElementById('backBtn').addEventListener('click', goBack);
            document.getElementById('forwardBtn').addEventListener('click', goForward);
            document.getElementById('refreshDirBtn').addEventListener('click', refreshCurrentDirectory);
            document.getElementById('rootDirBtn').addEventListener('click', () => navigateTo(''));
            document.getElementById('itemFilter').addEventListener('input', filterDirectoryItems);
            document.getElementById('refreshFileBtn').addEventListener('click', loadCurrentLogFile);
            document.getElementById('logLevelFilter').addEventListener('change', filterLogByLevel);
        });
        
        /**
         * 加载指定路径的目录内容
         */
        async function loadDirectoryContent(path) {
            const directoryContent = document.getElementById('directoryContent');
            
            // 显示加载状态
            directoryContent.innerHTML = `
                <div class="flex justify-center p-8 text-gray-500">
                    <i class="fa fa-circle-o-notch fa-spin mr-2"></i>加载目录内容中...
                </div>
            `;
            
            try {
                // 调用API获取目录内容
                const response = await fetch(`${API_BASE_URL}/directory?path=${encodeURIComponent(path)}`);
                
                if (!response.ok) {
                    throw new Error(`获取目录内容失败，状态码: ${response.status}`);
                }
                
                const data = await response.json();
                
                if (!data || !Array.isArray(data.items)) {
                    throw new Error('目录数据格式不正确');
                }
                
                // 更新当前路径
                currentPath = path;
                
                // 更新历史记录
                updateHistory(path);
                
                // 渲染目录内容
                renderDirectoryContent(data.items);
                
                // 更新面包屑导航
                updateBreadcrumb(path);
                
                // 更新导航按钮状态
                updateNavigationButtons();
                
                // 重置文件内容显示
                resetFileContent();
                
            } catch (error) {
                directoryContent.innerHTML = `
                    <div class="p-4 text-danger text-center">
                        <i class="fa fa-exclamation-circle mr-1"></i>${error.message || '加载目录失败'}
                    </div>
                `;
                console.error('加载目录内容失败:', error);
            }
        }
        
        /**
         * 渲染目录内容（文件夹和文件）
         */
        function renderDirectoryContent(items) {
            const directoryContent = document.getElementById('directoryContent');
            const itemCountElement = document.getElementById('itemCount');
            
            // 更新项目计数
            itemCountElement.textContent = `${items.length} 项`;
            
            if (items.length === 0) {
                directoryContent.innerHTML = `
                    <div class="p-4 text-center text-gray-500">
                        <i class="fa fa-info-circle mr-1"></i>该目录下没有内容
                    </div>
                `;
                return;
            }
            
            let html = '';
            
            // 先渲染文件夹，再渲染文件
            const directories = items.filter(item => item.isDirectory);
            const files = items.filter(item => !item.isDirectory);
            
            // 渲染文件夹
            directories.forEach(dir => {
                html += `
                    <div class="directory-item mb-1">
                        <button 
                            class="w-full text-left px-3 py-2 rounded hover:bg-gray-100 transition flex items-center"
                            data-name="${dir.name}"
                        >
                            <i class="fa fa-folder text-warning mr-2"></i>
                            <span>${dir.name}</span>
                        </button>
                    </div>
                `;
            });
            
            // 渲染文件
            files.forEach(file => {
                // 格式化文件大小和修改时间
                const fileSize = formatFileSize(file.fileSize || 0);
                const lastWriteTime = file.lastWriteTime 
                    ? new Date(file.lastWriteTime).toLocaleString() 
                    : '未知时间';
                
                html += `
                    <div class="file-item mb-1">
                        <button 
                            class="w-full text-left px-3 py-2 rounded hover:bg-gray-100 transition flex flex-col sm:flex-row sm:justify-between sm:items-center"
                            data-name="${file.name}"
                        >
                            <div class="flex items-center">
                                <i class="fa fa-file-text-o text-primary mr-2"></i>
                                <span class="truncate max-w-[200px] sm:max-w-none">${file.name}</span>
                            </div>
                            <div class="text-xs text-gray-500 mt-1 sm:mt-0">
                                ${fileSize} · ${lastWriteTime}
                            </div>
                        </button>
                    </div>
                `;
            });
            
            directoryContent.innerHTML = html;
            
            // 绑定文件夹点击事件（进入子目录）
            document.querySelectorAll('.directory-item button').forEach(btn => {
                btn.addEventListener('click', () => {
                    const dirName = btn.getAttribute('data-name');
                    // 构建新路径
                    const newPath = currentPath 
                        ? `${currentPath}/${dirName}` 
                        : dirName;
                    
                    navigateTo(newPath);
                });
            });
            
            // 绑定文件点击事件（查看日志内容）
            document.querySelectorAll('.file-item button').forEach(btn => {
                btn.addEventListener('click', () => {
                    // 移除其他文件的选中状态
                    document.querySelectorAll('.file-item button').forEach(b => {
                        b.classList.remove('bg-primary/10', 'font-medium');
                    });
                    
                    // 添加当前文件的选中状态
                    btn.classList.add('bg-primary/10', 'font-medium');
                    
                    const fileName = btn.getAttribute('data-name');
                    currentFile = fileName;
                    loadLogFileContent(currentPath, fileName);
                });
            });
        }
        
        /**
         * 导航到指定路径
         */
        function navigateTo(path) {
            loadDirectoryContent(path);
        }
        
        /**
         * 返回上一级目录
         */
        function goBack() {
            if (historyIndex > 0) {
                historyIndex--;
                const previousPath = pathHistory[historyIndex];
                loadDirectoryContent(previousPath);
            }
        }
        
        /**
         * 前进到下一级目录
         */
        function goForward() {
            if (historyIndex < pathHistory.length - 1) {
                historyIndex++;
                const nextPath = pathHistory[historyIndex];
                loadDirectoryContent(nextPath);
            }
        }
        
        /**
         * 刷新当前目录
         */
        function refreshCurrentDirectory() {
            loadDirectoryContent(currentPath);
        }
        
        /**
         * 更新历史记录
         */
        function updateHistory(path) {
            // 如果是新路径，清除当前索引后的历史
            if (historyIndex < pathHistory.length - 1) {
                pathHistory = pathHistory.slice(0, historyIndex + 1);
            }
            
            // 添加新路径（如果与最后一个路径不同）
            if (pathHistory.length === 0 || pathHistory[pathHistory.length - 1] !== path) {
                pathHistory.push(path);
                historyIndex = pathHistory.length - 1;
            }
        }
        
        /**
         * 更新面包屑导航
         */
        function updateBreadcrumb(path) {
            const breadcrumbContainer = document.getElementById('breadcrumbContainer');
            breadcrumbContainer.innerHTML = '';
            
            if (!path) {
                return; // 根目录没有额外的面包屑
            }
            
            // 拆分路径为各个部分
            const pathParts = path.split('/').filter(part => part);
            let currentSubPath = '';
            
            pathParts.forEach((part, index) => {
                // 构建当前部分的路径
                currentSubPath = currentSubPath 
                    ? `${currentSubPath}/${part}` 
                    : part;
                
                const breadcrumbItem = document.createElement('span');
                breadcrumbItem.className = 'breadcrumb-item';
                
                // 最后一部分只是文本，不是链接
                if (index === pathParts.length - 1) {
                    breadcrumbItem.innerHTML = `<span class="text-gray-700">${part}</span>`;
                } else {
                    // 前面的部分是可点击的链接
                    const btn = document.createElement('button');
                    btn.className = 'text-primary hover:underline';
                    btn.textContent = part;
                    btn.addEventListener('click', () => navigateTo(currentSubPath));
                    breadcrumbItem.appendChild(btn);
                }
                
                breadcrumbContainer.appendChild(breadcrumbItem);
            });
        }
        
        /**
         * 更新导航按钮状态
         */
        function updateNavigationButtons() {
            const backBtn = document.getElementById('backBtn');
            const forwardBtn = document.getElementById('forwardBtn');
            
            // 回退按钮状态：如果有上一级历史则启用
            backBtn.disabled = historyIndex <= 0;
            
            // 前进按钮状态：如果有下一级历史则启用
            forwardBtn.disabled = historyIndex >= pathHistory.length - 1;
        }
        
        /**
         * 过滤目录项（文件夹和文件）
         */
        function filterDirectoryItems() {
            const filterText = (document.getElementById('itemFilter').value || '').toLowerCase();
            const dirItems = document.querySelectorAll('.directory-item');
            const fileItems = document.querySelectorAll('.file-item');
            
            // 过滤文件夹
            dirItems.forEach(item => {
                const dirName = item.querySelector('button').getAttribute('data-name').toLowerCase();
                item.style.display = dirName.includes(filterText) ? '' : 'none';
            });
            
            // 过滤文件
            fileItems.forEach(item => {
                const fileName = item.querySelector('button').getAttribute('data-name').toLowerCase();
                item.style.display = fileName.includes(filterText) ? '' : 'none';
            });
        }
        
        /**
         * 加载日志文件内容
         */
        async function loadLogFileContent(dir, fileName) {
            // 参数验证
            if (!fileName || typeof fileName !== 'string') {
                console.error('无效的文件名:', fileName);
                return;
            }
            
            const contentContainer = document.getElementById('logContentContainer');
            const currentFileNameElement = document.getElementById('currentFileName');
            const downloadBtn = document.getElementById('downloadBtn');
            const refreshFileBtn = document.getElementById('refreshFileBtn');
            const logLevelFilter = document.getElementById('logLevelFilter');
            
            // 更新UI状态
            currentFileNameElement.textContent = fileName;
            contentContainer.innerHTML = `
                <div class="flex justify-center items-center h-full text-gray-400">
                    <i class="fa fa-circle-o-notch fa-spin mr-2"></i>加载日志内容中...
                </div>
            `;
            downloadBtn.disabled = false;
            refreshFileBtn.disabled = false;
            logLevelFilter.disabled = false;
            
            try {
                // 构建请求参数
                const params = new URLSearchParams();
                if (dir) params.append('dir', dir);
                params.append('file', fileName);
                
                const response = await fetch(`${API_BASE_URL}/content?${params.toString()}`);
                
                if (!response.ok) {
                    throw new Error(`获取日志内容失败，状态码: ${response.status}`);
                }
                
                const data = await response.json();
                
                if (typeof data.content !== 'string') {
                    throw new Error('日志内容格式不正确');
                }
                
                renderLogContent(data.content);
                updateLogStats(data.lineCount || 0);
                
                // 更新下载按钮事件
                downloadBtn.onclick = () => {
                    const downloadParams = new URLSearchParams();
                    if (dir) downloadParams.append('dir', dir);
                    downloadParams.append('file', fileName);
                    window.location.href = `${API_BASE_URL}/download?${downloadParams.toString()}`;
                };
                
            } catch (error) {
                contentContainer.innerHTML = `
                    <div class="p-4 text-danger text-center">
                        <i class="fa fa-exclamation-circle mr-1"></i>${error.message || '读取日志内容失败'}
                    </div>
                `;
                console.error('加载日志内容失败:', error);
            }
        }
        
        /**
         * 重新加载当前日志文件
         */
        function loadCurrentLogFile() {
            if (currentPath !== null && currentFile) {
                loadLogFileContent(currentPath, currentFile);
            }
        }
        
        /**
         * 渲染日志内容
         */
        function renderLogContent(content) {
            const contentContainer = document.getElementById('logContentContainer');
            
            if (!content) {
                contentContainer.innerHTML = `
                    <div class="text-center p-4 text-gray-400">
                        <i class="fa fa-info-circle mr-1"></i>日志文件为空
                    </div>
                `;
                return;
            }
            
            // 按行拆分日志
            const lines = content.split('\n');
            let html = '';
            
            lines.forEach(line => {
                // 确保line是字符串
                const lineStr = String(line);
                let levelClass = '';
                
                // 根据日志级别添加样式
                if (lineStr.includes('ERROR') || lineStr.includes('FATAL')) {
                    levelClass = 'text-danger';
                } else if (lineStr.includes('WARN')) {
                    levelClass = 'text-warning';
                } else if (lineStr.includes('INFO')) {
                    levelClass = 'text-success';
                }
                
                html += `<div class="log-line ${levelClass} mb-1">${escapeHtml(lineStr)}</div>`;
            });
            
            contentContainer.innerHTML = html;
        }
        
        /**
         * 按日志级别过滤
         */
        function filterLogByLevel() {
            const selectedLevel = document.getElementById('logLevelFilter').value;
            const logLines = document.querySelectorAll('.log-line');
            
            if (selectedLevel === 'all') {
                logLines.forEach(line => {
                    line.style.display = '';
                });
                return;
            }
            
            // 确保selectedLevel是字符串
            const levelStr = String(selectedLevel).toUpperCase();
            
            logLines.forEach(line => {
                const lineText = String(line.textContent);
                if (lineText.includes(levelStr)) {
                    line.style.display = '';
                } else {
                    line.style.display = 'none';
                }
            });
        }
        
        /**
         * 更新日志统计信息
         */
        function updateLogStats(lineCount) {
            const logStatsElement = document.getElementById('logStats');
            logStatsElement.textContent = `共 ${lineCount} 行日志`;
        }
        
        /**
         * 格式化文件大小
         */
        function formatFileSize(bytes) {
            if (typeof bytes !== 'number' || isNaN(bytes) || bytes < 0) {
                return '0 B';
            }
            
            if (bytes < 1024) {
                return `${bytes} B`;
            } else if (bytes < 1024 * 1024) {
                return `${(bytes / 1024).toFixed(2)} KB`;
            } else if (bytes < 1024 * 1024 * 1024) {
                return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
            } else {
                return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
            }
        }
        
        /**
         * HTML转义，防止XSS攻击
         */
        function escapeHtml(unsafe) {
            if (typeof unsafe !== 'string') {
                return '';
            }
            return unsafe
                .replace(/&/g, "&amp;")
                .replace(/</g, "&lt;")
                .replace(/>/g, "&gt;")
                .replace(/"/g, "&quot;")
                .replace(/'/g, "&#039;");
        }
        
        /**
         * 重置文件内容显示
         */
        function resetFileContent() {
            document.getElementById('logContentContainer').innerHTML = `
                <div class="flex justify-center items-center h-full text-gray-400">
                    <div class="text-center">
                        <i class="fa fa-file-text-o text-5xl mb-4"></i>
                        <p>浏览左侧目录并选择日志文件查看内容</p>
                    </div>
                </div>
            `;
            document.getElementById('currentFileName').textContent = '请选择日志文件';
            document.getElementById('downloadBtn').disabled = true;
            document.getElementById('refreshFileBtn').disabled = true;
            document.getElementById('logLevelFilter').disabled = true;
            document.getElementById('logStats').textContent = '未选择文件';
            currentFile = null;
        }
    </script>
</body>
</html>
    